zynqmp: Fix EG/EV detection logic
authorSiva Durga Prasad Paladugu <sivadur@xilinx.com>
Mon, 5 Mar 2018 13:17:15 +0000 (18:47 +0530)
committerSiva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com>
Thu, 17 May 2018 09:49:23 +0000 (15:19 +0530)
The vcu disable bit in efuse ipdisable register is valid
only if PL powered up so, consider PL powerup status for
determing EG/EV part. If PL is not powered up, display
EG/EV as a part of string. The PL powerup status will
be filled by pmufw based on PL PROGB status in the
9th bit of version field.This patch also used IPI
to get this info from pmufw instead of directly accessing
the registers. Accessing this info from pmufw using
IPI fixes the issue of PMUFW access denied error for
reading IPDISABLE register.

Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
plat/xilinx/zynqmp/aarch64/zynqmp_common.c
plat/xilinx/zynqmp/zynqmp_def.h

index 916e7129ae441fd2fad509ec542e60c4cef14c51..b144c84bd4998200e9fa3a082291ec6d846e079b 100644 (file)
@@ -8,6 +8,8 @@
 #include <generic_delay_timer.h>
 #include <mmio.h>
 #include <platform.h>
+#include <stdbool.h>
+#include <string.h>
 #include <xlat_tables.h>
 #include "../zynqmp_private.h"
 #include "pm_api_sys.h"
@@ -62,6 +64,7 @@ static const struct {
        unsigned int id;
        unsigned int ver;
        char *name;
+       bool evexists;
 } zynqmp_devices[] = {
        {
                .id = 0x10,
@@ -84,11 +87,13 @@ static const struct {
        {
                .id = 0x20,
                .name = "5EV",
+               .evexists = true,
        },
        {
                .id = 0x20,
                .ver = 0x100,
                .name = "5EG",
+               .evexists = true,
        },
        {
                .id = 0x20,
@@ -98,11 +103,13 @@ static const struct {
        {
                .id = 0x21,
                .name = "4EV",
+               .evexists = true,
        },
        {
                .id = 0x21,
                .ver = 0x100,
                .name = "4EG",
+               .evexists = true,
        },
        {
                .id = 0x21,
@@ -112,11 +119,13 @@ static const struct {
        {
                .id = 0x30,
                .name = "7EV",
+               .evexists = true,
        },
        {
                .id = 0x30,
                .ver = 0x100,
                .name = "7EG",
+               .evexists = true,
        },
        {
                .id = 0x30,
@@ -188,41 +197,49 @@ static const struct {
        },
 };
 
-static unsigned int zynqmp_get_silicon_id(void)
+#define ZYNQMP_PL_STATUS_BIT   9
+#define ZYNQMP_PL_STATUS_MASK  BIT(ZYNQMP_PL_STATUS_BIT)
+#define ZYNQMP_CSU_VERSION_MASK        ~(ZYNQMP_PL_STATUS_MASK)
+
+static char *zynqmp_get_silicon_idcode_name(void)
 {
-       uint32_t id;
+       uint32_t id, ver, chipid[2];
+       size_t i, j, len;
+       enum pm_ret_status ret;
+       const char *name = "EG/EV";
 
-       id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
+       ret = pm_get_chipid(chipid);
+       if (ret)
+               return "UNKN";
 
-       id &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK;
+       id = chipid[0] & (ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
+                         ZYNQMP_CSU_IDCODE_SVD_MASK);
        id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
+       ver = chipid[1] >> ZYNQMP_EFUSE_IPDISABLE_SHIFT;
 
-       return id;
-}
-
-static unsigned int zynqmp_get_silicon_id2(void)
-{
-       uint32_t id;
-
-       id = mmio_read_32(EFUSE_BASEADDR + EFUSE_IPDISABLE_OFFSET);
-       id &= EFUSE_IPDISABLE_VERSION;
+       for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
+               if (zynqmp_devices[i].id == id &&
+                   zynqmp_devices[i].ver == (ver & ZYNQMP_CSU_VERSION_MASK))
+                       break;
+       }
 
-       return id;
-}
+       if (i >= ARRAY_SIZE(zynqmp_devices))
+               return "UNKN";
 
-static char *zynqmp_get_silicon_idcode_name(void)
-{
-       unsigned int id, ver;
-       size_t i;
+       if (!zynqmp_devices[i].evexists)
+               return zynqmp_devices[i].name;
 
-       id = zynqmp_get_silicon_id();
-       ver = zynqmp_get_silicon_id2();
+       if (ver & ZYNQMP_PL_STATUS_MASK)
+               return zynqmp_devices[i].name;
 
-       for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
-               if (zynqmp_devices[i].id == id && zynqmp_devices[i].ver == ver)
-                       return zynqmp_devices[i].name;
+       len = strlen(zynqmp_devices[i].name) - 2;
+       for (j = 0; j < strlen(name); j++) {
+               zynqmp_devices[i].name[len] = name[j];
+               len++;
        }
-       return "UNKN";
+       zynqmp_devices[i].name[len] = '\0';
+
+       return zynqmp_devices[i].name;
 }
 
 static unsigned int zynqmp_get_rtl_ver(void)
index 793be8b79d5bb928af718b8ecc47573c55c22af0..cf90bcd0717f0c15f751d2e4722fefadf1ec9f02 100644 (file)
 #define EFUSE_BASEADDR         0xFFCC0000
 #define EFUSE_IPDISABLE_OFFSET 0x1018
 #define EFUSE_IPDISABLE_VERSION        0x1FFU
+#define ZYNQMP_EFUSE_IPDISABLE_SHIFT   20
 
 /* Access control register defines */
 #define ACTLR_EL3_L2ACTLR_BIT  (1 << 6)